package org.testile.dataset.scriptable;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;

import org.testile.dataset.scriptable.handlers.ScriptInvocationHandler;
import javax.script.Bindings;

/**
 * Configures the usage of one scripting language with a prefix and a list of
 * invocation handlers.
 * 
 * @author Gunnar Morling
 */
public class ScriptableDataSetConfig {

	private final String prefix;

	private final String languageName;

	private final List<ScriptInvocationHandler> handlers = new ArrayList<ScriptInvocationHandler>();

	private final Bindings engineBinding;

	/**
	 * Creates a new ScriptableDataSetConfig.
	 * 
	 * @param languageName
	 *            The name of the language as expected by the JSR 223 scripting
	 *            engine manager, e.g. "jruby". May not be null.
	 * @param prefix
	 *            A prefix, which shall precede fields in a ScriptableDataSet in
	 *            that language, e.g. "jruby:". May not be null.
	 */
	public ScriptableDataSetConfig(String languageName, String prefix) {

		this(languageName, prefix, null, null);
	}
	
	/**
	 * Creates a new ScriptableDataSetConfig.
	 *
	 * @param languageName
	 *            The name of the language as expected by the JSR 223 scripting
	 *            engine manager, e.g. "jruby". May not be null.
	 * @param prefix
	 *            A prefix, which shall precede fields in a ScriptableDataSet in
	 *            that language, e.g. "jruby:". May not be null.
	 * @param handlers
	 *            An optional list with handlers to be applied for fields with
	 *            the given prefix.
	 */
	public ScriptableDataSetConfig(String languageName, String prefix,
			List<ScriptInvocationHandler> handlers) {

		this(languageName, prefix, null, handlers);
	}

	/**
	 * Creates a new ScriptableDataSetConfig.
	 *
	 * @param languageName
	 *            The name of the language as expected by the JSR 223 scripting
	 *            engine manager, e.g. "jruby". May not be null.
	 * @param prefix
	 *            A prefix, which shall precede fields in a ScriptableDataSet in
	 *            that language, e.g. "jruby:". May not be null.
	 * @param engineBinding
	 *            a <code>Bindings</code> of named values to be used by scripts.
	 */
	public ScriptableDataSetConfig(String languageName, String prefix, Bindings engineBinding) {

		this(languageName, prefix, engineBinding, null);
	}

	/**
	 * Creates a new ScriptableDataSetConfig.
	 *
	 * @param languageName
	 *            The name of the language as expected by the JSR 223 scripting
	 *            engine manager, e.g. "jruby". May not be null.
	 * @param prefix
	 *            A prefix, which shall precede fields in a ScriptableDataSet in
	 *            that language, e.g. "jruby:". May not be null.
	 * @param engineBinding
	 *            a <code>Bindings</code> of named values to be used by scripts.
	 * @param handlers
	 *            An optional list with handlers to be applied for fields with
	 *            the given prefix.
	 */
	public ScriptableDataSetConfig(String languageName, String prefix, Bindings engineBinding,
			List<ScriptInvocationHandler> handlers) {

		Validate.notNull(languageName);
		Validate.notNull(prefix);

		this.prefix = prefix;
		this.languageName = languageName;
		this.engineBinding = engineBinding;

		if (handlers != null) {
			this.handlers.addAll(handlers);
		}
	}

	public String getPrefix() {
		return prefix;
	}

	public String getLanguageName() {
		return languageName;
	}

	public Bindings getBindings() {
		return engineBinding;
	}

	public List<ScriptInvocationHandler> getHandlers() {
		return handlers;
	}

	@Override
	public String toString() {
		return ReflectionToStringBuilder.toString(this);
	}
}
